﻿package net.wangit.view.element;

import net.wangit.Element;
import net.wangit.Page;
import net.wangit.Row;
import net.wangit.constants.ElementShowMode;
import net.wangit.context.ActionContext;
import net.wangit.framework.expression.LabelExpression;
import net.wangit.support.ElementWriter;
import net.wangit.util.HtmlUtil;
import net.wangit.view.unit.UnitComponent;
import net.wangit.view.util.Html;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public abstract class ElementComponent implements Element, Cloneable {

	private static Log log = LogFactory
			.getLog(net.wangit.view.element.ElementComponent.class);
	private static final String REQUIRED_HTML = "<span class=\"ER\">*</span>";
	private static final String HTML_KEY = "0";
	private static final String OBJECT_KEY = "1";
	private static final String SHOW_MODE_KEY = "2";
	private static final String COMBINE_ROWS_KEY = "3";
	private String html;
	private String id;
	protected String name;
	private String link;
	private String title;
	private String defaultValue;
	private String custom;
	private String css;
	private int width;
	private int height;
	private String groupId;
	private boolean isToolbarElement;
	protected int showMode;
	private Object object;
	private boolean required;
	private boolean markRequired;
	private int minLength;
	private int maxLength;
	private int scale;
	private String validator;
	private String customValidator;
	private String validationExpression;
	private int sort;
	private int scanShowMode;
	private int editShowMode;
	private int addShowMode;
	private boolean isAction;
	private boolean addLabel;
	protected UnitComponent parent;
	private boolean hasAccessPrivilege;
	private int rejectResult;
	private String prefix;
	private String suffix;
	private int tdWidth;
	private int tdWidthMode;
	private int tdHeight;
	private int tdHeightMode;
	private String tdCss;
	private String tdCustom;
	private int tdRowSpan;
	private int tdColSpan;
	private int tdAlign;
	private int tdVerticalAlign;
	private int tdPaddingTop;
	private int tdPaddingBottom;
	private int tdPaddingLeft;
	private int tdPaddingRight;
	private ElementExtendedAttribute eea;

	public ElementComponent() {
		isToolbarElement = false;
		showMode = -1;
		scanShowMode = 1;
		editShowMode = 3;
		addShowMode = 3;
		isAction = false;
		addLabel = false;
		hasAccessPrivilege = false;
		tdRowSpan = 1;
		tdColSpan = 1;
		tdPaddingTop = -1;
		tdPaddingBottom = -1;
		tdPaddingLeft = -1;
		tdPaddingRight = -1;
	}

	public String getText(ActionContext ac, String value) {
		return value;
	}

	public void write(ActionContext ac, StringBuffer html, int rowIndex, Row row) {
		setRowIndex(rowIndex);
		String htmlResult = getHtml();
		if (htmlResult != null) {
			html.append(htmlResult);
		} else {
			Html.set(html, LabelExpression.resolve(ac, getPrefix()));
			getWriter().write(ac, html, this, row);
			if (isRequired() && isMarkRequired()) {
				int showMode = getShowMode();
				if (showMode == ElementShowMode.CONTROL
						|| showMode == ElementShowMode.READONLY)
					html.append(ElementComponent.REQUIRED_HTML);
			}
			Html.set(html, LabelExpression.resolve(ac, getSuffix()));
		}
	}

	public void writeTd(ActionContext ac, StringBuffer html, int rowIndex) {
		html.append("<td");
		Html.setCss(html, getTdCss());
		Html.setRowSpan(html, tdRowSpan * getCombineRows());
		Html.setColSpan(html, tdColSpan);
		Html.setAlign(html, getTdAlign());
		Html.setVerticalAlign(html, getTdVerticalAlign());
		Html.setAttribute(html, getTdAttribute());
		Html.setWidth(html, tdWidth, tdWidthMode);
		Html.setHeight(html, getTdHeight(), getTdHeightMode());
		if (tdPaddingTop >= 0 || tdPaddingLeft >= 0 || tdPaddingBottom >= 0
				|| tdPaddingRight >= 0)
			Html.setPadding(html, tdPaddingTop, tdPaddingLeft, tdPaddingBottom,
					tdPaddingRight);
		html.append(">");
	}

	public void validate(ActionContext actioncontext,
			StringBuffer stringbuffer, String s) {
	}

	public String getGroupId() {
		return groupId;
	}

	public void setGroupId(String groupId) {
		this.groupId = groupId;
	}

	public boolean isToolbarElement() {
		return isToolbarElement;
	}

	public void setIsToolbarElement(boolean isToolbarElement) {
		this.isToolbarElement = isToolbarElement;
	}

	public String getCustom() {
		return getString("cu", custom);
	}

	public void setCustom(String custom) {
		this.custom = custom;
	}

	public void setCustom(int rowIndex, String custom) {
		getExtendedAttribute().set(rowIndex, "cu", custom);
	}

	public void setCss(String css) {
		this.css = css;
	}

	public void setCss(int rowIndex, String css) {
		getExtendedAttribute().set(rowIndex, "css", css);
	}

	public void setDefaultValue(String defaultValue) {
		this.defaultValue = defaultValue;
	}

	public void setDefaultValue(int rowIndex, String defaultValue) {
		getExtendedAttribute().set(rowIndex, "d", defaultValue);
	}

	public void setHeight(int height) {
		this.height = height;
	}

	public void setHeight(int rowIndex, int height) {
		getExtendedAttribute().set(rowIndex, "h", height);
	}

	public String getId() {
		return id;
	}

	public void setLink(String link) {
		this.link = link;
	}

	public void setLink(int rowIndex, String link) {
		getExtendedAttribute().set(rowIndex, "l", link);
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setName(int rowIndex, String name) {
		getExtendedAttribute().set(rowIndex, "n", name);
	}

	public void setShowMode(int showMode) {
		this.showMode = showMode;
	}

	public void setShowMode(int rowIndex, int showMode) {
		getExtendedAttribute().set(rowIndex, ElementComponent.SHOW_MODE_KEY,
				showMode);
	}

	public void setCombineRows(int rowIndex, int combineRows) {
		getExtendedAttribute().set(rowIndex, ElementComponent.COMBINE_ROWS_KEY,
				combineRows);
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public void setTitle(int rowIndex, String title) {
		getExtendedAttribute().set(rowIndex, "t", title);
	}

	public void setWidth(int width) {
		this.width = width;
	}

	public void setWidth(int rowIndex, int width) {
		getExtendedAttribute().set(rowIndex, "w", width);
	}

	public Object getObject() {
		return getObject(ElementComponent.OBJECT_KEY, object);
	}

	public void setObject(Object object) {
		this.object = object;
	}

	public void setObject(int rowIndex, Object object) {
		getExtendedAttribute().set(rowIndex, ElementComponent.OBJECT_KEY,
				object);
	}

	protected abstract void configure(Row row);

	protected abstract ElementWriter getWriter();

	public String getValue4Validation(String value) {
		if (value.length() > 30) {
			value = new StringBuilder(value.substring(0, 30)).append("...")
					.toString();
		}
		return HtmlUtil.replaceTags(value);
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return getString("n", name);
	}

	public String getCss() {
		return getString("css", css);
	}

	public String getDefaultValue() {
		return getString("d", defaultValue);
	}

	public int getHeight() {
		return getInt("h", height);
	}

	public String getLink() {
		return getString("l", link);
	}

	public String getTitle() {
		return getString("t", title);
	}

	public int getWidth() {
		return getInt("w", width);
	}

	public boolean isAddLabel() {
		return addLabel;
	}

	protected void setRowIndex(int index) {
		if (eea != null)
			eea.setCurrentRowIndex(index);
	}

	public int getShowMode() {
		int customShowMode = getInt(ElementComponent.SHOW_MODE_KEY, showMode);
		if (customShowMode < 0)
			return getDefaultShowMode();
		else
			return customShowMode;
	}

	private int getDefaultShowMode() {
		if (parent == null)
			return 3;
		String unitShowMode = parent.getShowMode();
		if ("s".equals(unitShowMode))
			return scanShowMode;
		if ("e".equals(unitShowMode))
			return editShowMode;
		else
			return addShowMode;
	}

	public UnitComponent getParent() {
		return parent;
	}

	public void setParent(UnitComponent unit) {
		parent = unit;
	}

	public boolean isAction() {
		return isAction;
	}

	protected void setIsAction(boolean isAction) {
		this.isAction = isAction;
	}

	public boolean isRequired() {
		return required;
	}

	protected void setRequired(boolean required) {
		this.required = required;
	}

	protected void setAddShowMode(int addShowMode) {
		this.addShowMode = addShowMode;
	}

	protected void setEditShowMode(int editShowMode) {
		this.editShowMode = editShowMode;
	}

	protected void setScanShowMode(int scanShowMode) {
		this.scanShowMode = scanShowMode;
	}

	public final void moveExtendedAttribute(int beginRowIndex, int endRowIndex) {
		if (eea != null)
			eea.move(beginRowIndex, endRowIndex);
	}

	private final String getHtml() {
		return getString(ElementComponent.HTML_KEY, html);
	}

	public final void setHtml(String html) {
		this.html = html;
	}

	public final void setHtml(int i, String content) {
		getExtendedAttribute().set(i, ElementComponent.HTML_KEY, content);
	}

	public final boolean hasAccessPrivilege() {
		return hasAccessPrivilege;
	}

	protected final void setHasAccessPrivilege(boolean hasAccessPrivilege) {
		this.hasAccessPrivilege = hasAccessPrivilege;
	}

	public int getMinLength() {
		return minLength;
	}

	public int getMaxLength() {
		return maxLength;
	}

	public int getScale() {
		return scale;
	}

	public String getValidationExpression() {
		return validationExpression;
	}

	public String getCustomValidator() {
		return customValidator;
	}

	public String getValidator() {
		return validator;
	}

	public int getQueryMode() {
		return 1;
	}

	public int getRejectResult() {
		return rejectResult;
	}

	protected void setRejectResult(int rejectResult) {
		this.rejectResult = rejectResult;
	}

	public boolean isMarkRequired() {
		return markRequired;
	}

	protected void setMarkRequired(boolean markRequired) {
		this.markRequired = markRequired;
	}

	public void setAddLabel(boolean addLabel) {
		this.addLabel = addLabel;
	}

	public int getSort() {
		return sort;
	}

	public void setSort(int sort) {
		this.sort = sort;
	}

	public String getPrefix() {
		return getString("wp", prefix);
	}

	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}

	public void setPrefix(int rowIndex, String prefix) {
		getExtendedAttribute().set(rowIndex, "wp", prefix);
	}

	public String getSuffix() {
		return getString("ws", suffix);
	}

	public void setSuffix(String suffix) {
		this.suffix = suffix;
	}

	public void setSuffix(int rowIndex, String suffix) {
		getExtendedAttribute().set(rowIndex, "ws", suffix);
	}

	public int getTdAlign() {
		return getInt("wa", tdAlign);
	}

	public void setTdAlign(int tdAlign) {
		this.tdAlign = tdAlign;
	}

	public void setTdAlign(int rowIndex, int tdAlign) {
		getExtendedAttribute().set(rowIndex, "wa", tdAlign);
	}

	public int getTdVerticalAlign() {
		return getInt("wv", tdVerticalAlign);
	}

	public void setTdVerticalAlign(int tdVerticalAlign) {
		this.tdVerticalAlign = tdVerticalAlign;
	}

	public void setTdVerticalAlign(int rowIndex, int tdVerticalAlign) {
		getExtendedAttribute().set(rowIndex, "wv", tdVerticalAlign);
	}

	public String getTdAttribute() {
		return getString("wcu", tdCustom);
	}

	public void setTdCustom(String tdCustom) {
		this.tdCustom = tdCustom;
	}

	public void setTdCustom(int rowIndex, String tdCustom) {
		getExtendedAttribute().set(rowIndex, "wcu", tdCustom);
	}

	public int getTdColSpan() {
		return tdColSpan;
	}

	public void setTdColSpan(int tdColSpan) {
		this.tdColSpan = tdColSpan >= 0 ? tdColSpan : 1;
	}

	public String getTdCss() {
		return getString("wc", tdCss);
	}

	public void setTdCss(String tdCss) {
		this.tdCss = tdCss;
	}

	public void setTdCss(int rowIndex, String tdCss) {
		getExtendedAttribute().set(rowIndex, "wc", tdCss);
	}

	public int getTdHeight() {
		return getInt("wh", tdHeight);
	}

	public int getCombineRows() {
		return getInt(ElementComponent.COMBINE_ROWS_KEY, 1);
	}

	public void setTdHeight(int tdHeight) {
		this.tdHeight = tdHeight;
	}

	public void setTdHeight(int rowIndex, int tdHeight) {
		getExtendedAttribute().set(rowIndex, "wh", tdHeight);
	}

	public int getTdHeightMode() {
		return tdHeightMode;
	}

	public void setTdHeightMode(int tdHeightMode) {
		this.tdHeightMode = tdHeightMode;
	}

	public int getTdRowSpan() {
		return tdRowSpan;
	}

	public void setTdRowSpan(int tdRowSpan) {
		this.tdRowSpan = tdRowSpan >= 0 ? tdRowSpan : 1;
	}

	public int getTdWidth() {
		return tdWidth;
	}

	public void setTdWidth(int tdWidth) {
		this.tdWidth = tdWidth;
	}

	public int getTdWidthMode() {
		return tdWidthMode;
	}

	public void setTdWidthMode(int tdWidthMode) {
		this.tdWidthMode = tdWidthMode;
	}

	public int getTdPaddingBottom() {
		return tdPaddingBottom;
	}

	public void setTdPaddingBottom(int tdPaddingBottom) {
		this.tdPaddingBottom = tdPaddingBottom;
	}

	public int getTdPaddingLeft() {
		return tdPaddingLeft;
	}

	public void setTdPaddingLeft(int tdPaddingLeft) {
		this.tdPaddingLeft = tdPaddingLeft;
	}

	public int getTdPaddingRight() {
		return tdPaddingRight;
	}

	public void setTdPaddingRight(int tdPaddingRight) {
		this.tdPaddingRight = tdPaddingRight;
	}

	public int getTdPaddingTop() {
		return tdPaddingTop;
	}

	public void setTdPaddingTop(int tdPaddingTop) {
		this.tdPaddingTop = tdPaddingTop;
	}

	protected abstract void cloneAfter(ActionContext actioncontext, Page page);

	public ElementComponent cloneElement(ActionContext ac, Page page) {
		ElementComponent ec;
		try {
			ec = (ElementComponent) super.clone();
			ec.cloneAfter(ac, page);
			return ec;
		} catch (Exception e) {
			log.error(e);
			return null;
		}
	}

	private ElementExtendedAttribute getExtendedAttribute() {
		if (eea == null)
			eea = new ElementExtendedAttribute();
		return eea;
	}

	private Object getObject(String name, Object defaultObject) {
		if (eea == null)
			return defaultObject;
		else
			return eea.getObject(name, defaultObject);
	}

	private String getString(String name, String defaultValue) {
		if (eea == null)
			return defaultValue;
		else
			return eea.getString(name, defaultValue);
	}

	private int getInt(String name, int defaultValue) {
		if (eea == null)
			return defaultValue;
		else
			return eea.getInt(name, defaultValue);
	}

	protected void setCustomValidator(String customValidator) {
		this.customValidator = customValidator;
	}

	protected void setMaxLength(int maxLength) {
		this.maxLength = maxLength;
	}

	protected void setMinLength(int minLength) {
		this.minLength = minLength;
	}

	protected void setScale(int scale) {
		this.scale = scale;
	}

	protected void setValidationExpression(String validationExpression) {
		this.validationExpression = validationExpression;
	}

	protected void setValidator(String validator) {
		this.validator = validator;
	}

}
